/*
@author https://yunp.top
 */

@file:JsQualifier("starling.textures")

package starling.textures

import openfl.display.Bitmap
import openfl.display.BitmapData
import openfl.display3D.textures.TextureBase
import openfl.events.ErrorEvent
import openfl.geom.Matrix
import openfl.geom.Point
import openfl.geom.Rectangle
import starling.rendering.VertexData

open external class Texture {
    companion object {
        var asyncBitmapUploadEnabled: Boolean
        val maxSize: Int
        fun empty(
            width: Double,
            height: Double,
            premultipliedAlpha: Boolean = definedExternally,
            mipMapping: Boolean = definedExternally,
            optimizeForRenderToTexture: Boolean = definedExternally,
            scale: Double = definedExternally,
            format: String = definedExternally,
            forcePotTexture: Boolean = definedExternally
        ): Texture

        fun fromAtfData(
            data: openfl.utils.ByteArray,
            scale: Double = definedExternally,
            useMipMaps: Boolean = definedExternally,
            async: (texture: Texture) -> Unit = definedExternally,
            premultipliedAlpha: Boolean = definedExternally
        ): Texture

        fun fromBitmap(
            bitmap: Bitmap,
            generateMipMaps: Boolean = definedExternally,
            optimizeForRenderToTexture: Boolean = definedExternally,
            scale: Double = definedExternally,
            format: String = definedExternally,
            forcePotTexture: Boolean = definedExternally,
            async: (texture: Texture, error: ErrorEvent) -> Unit = definedExternally
        ): Texture

        fun fromBitmapData(
            data: BitmapData,
            generateMipMaps: Boolean = definedExternally,
            optimizeForRenderToTexture: Boolean = definedExternally,
            scale: Double = definedExternally,
            format: String = definedExternally,
            forcePotTexture: Boolean = definedExternally,
            async: (texture: Texture, error: ErrorEvent) -> Unit = definedExternally
        ): Texture

        fun fromColor(
            width: Double,
            height: Double,
            color: Long = definedExternally,
            alpha: Double = definedExternally,
            optimizeForRenderToTexture: Boolean = definedExternally,
            scale: Double = definedExternally,
            format: String = definedExternally,
            forcePotTexture: Boolean = definedExternally
        ): Texture

        fun fromData(data: Bitmap, options: TextureOptions = definedExternally): Texture
        fun fromData(data: BitmapData, options: TextureOptions = definedExternally): Texture
        fun fromData(atfData: ByteArray, options: TextureOptions = definedExternally): Texture
        fun fromTexture(
            texture: Texture,
            region: Rectangle = definedExternally,
            frame: Rectangle = definedExternally,
            rotated: Boolean = definedExternally,
            scaleModifier: Double = definedExternally
        ): Texture

        fun fromTextureBase(
            base: TextureBase,
            width: Int,
            height: Int,
            options: TextureOptions = definedExternally
        ): ConcreteTexture

        fun getMaxSize(textureFormat: String = definedExternally): Int
    }

    val base: TextureBase
    val format: String
    val frame: Rectangle
    val frameHeight: Double
    val frameWidth: Double
    val height: Double
    val mipMapping: Boolean
    val nativeHeight: Double
    val nativeWidth: Double
    val premultipliedAlpha: Boolean
    val root: ConcreteTexture
    val scale: Double
    val transformationMatrix: Matrix
    val transformationMatrixToRoot: Matrix
    val width: Double

    fun dispose()
    fun getTexCoords(
        vertexData: VertexData,
        vertexID: Int,
        attrName: String = definedExternally,
        out: Point = definedExternally
    ): Point

    fun globalToLocal(u: Double, v: Double, out: Point = definedExternally): Point
    fun localToGlobal(u: Double, v: Double, out: Point = definedExternally): Point
    fun setTexCoords(vertexData: VertexData, vertexID: Int, attrName: String, u: Double, v: Double)
    fun setupTextureCoordinates(
        vertexData: VertexData,
        vertexID: Int = definedExternally,
        attrName: String = definedExternally
    )

    fun setupVertexPositions(
        vertexData: VertexData,
        vertexID: Int = definedExternally,
        attrName: String = definedExternally,
        bounds: Rectangle = definedExternally
    )
}